'use strict';

const _ = require('lodash');
const Service = require('egg').Service;

class TopicCollectSvc extends Service {
  getTopicCollect(userId, topicId) {
    const query = {user_id: userId, topic_id: topicId};
    return this.ctx.model.TopicCollect.findOne(query).exec();
  }

  getCollectUsersByTopicId(topicId) {
    const query = {topic_id: topicId};
    return this.ctx.model.TopicCollect.find(query).exec();
  }

  /**
   * 新增或修改收藏
   * @param {string} user_id 用户id
   * @param {string} topic_id 文章id
   * @param {string} title 文章标题(冗余)
   * @param {string} brief 收藏简介
   * @param {string} is_public 文章是否公开(冗余)
   * @param {string} original_url 文章的原始链接(冗余)
   * @param {array} tags 文章的收藏标签数组
   */
  async upsert(user_id, topic_id, title, brief, is_public, original_url, tags) {
    const user = await this.ctx.service.userSvc.getUserById(user_id);
    let auto_tags = user.auto_tags;
    if (auto_tags) {
      auto_tags = auto_tags.split('\r\n');
    } else {
      auto_tags = [];
    }
    let matching_tags = auto_tags.map(auto_tag => {
      let kv = auto_tag.split('=');
      let k = kv[0];
      let v = kv[1];
      if (original_url && original_url.includes(k)) {
        return v;
      }
    }).filter(v => v);


    let now = new Date();
    let upsertModel = {
      title: title,
      is_public: is_public,
      updatedAt: now,
      $setOnInsert: {createdAt: now}
    };
    if (original_url) {
      upsertModel.original_url = original_url;
    }
    if (brief != null) {
      upsertModel.brief = brief;
    }
    if (tags) {
      if (Array.isArray(tags)) {
        tags = tags.concat(matching_tags);
        upsertModel.tags = Array.from(new Set(tags));
      } else {
        tags = tags.trim().split(/\s+/).concat(matching_tags);
        upsertModel.tags = Array.from(new Set(tags));
      }
      upsertModel.tags = this.ctx.helper.getUniqueArrayCaseNotSensitive(upsertModel.tags);
    } else {
      upsertModel.tags = matching_tags;
    }
    return this.ctx.model.TopicCollect.updateOne({
      user_id: user_id,
      topic_id: topic_id
    }, upsertModel, {upsert: true});
  }

  remove(userId, topicId) {
    const query = {user_id: userId, topic_id: topicId};
    return this.ctx.model.TopicCollect.remove(query).exec();
  }

  removeAllUserCollect(topic_id) {
    const query = {topic_id: topic_id};
    return this.ctx.model.TopicCollect.remove(query).exec();
  }


  /**
   * 修改标签名
   * @param {string} user_id 用户id
   * @param {string} old_name 原标签名
   * @param {string} new_name 新标签名
   */
  async updateTagName(user_id, old_name, new_name) {
    return await this.ctx.model.TopicCollect.updateMany({
      user_id: user_id,
      tags: old_name
    }, {$set: {'tags.$': new_name, updatedAt: Date.now()}});
  }

  /**
   * 删除标签
   * @param {string} user_id 用户id
   * @param {string} name 要删除的标签名
   */
  async removeTag(user_id, name) {
    return await this.ctx.model.TopicCollect.updateMany({user_id: user_id, tags: name}, {$pull: {tags: name}});
  }


  /**
   * 查询用户收藏的文章
   * @param {string} user_id 用户id
   * @param {boolean} is_oneself 是否是本人
   * @param {string} keyword 搜索的词
   * @param {string} tag_name 收藏标签名
   * @param {number} page_index
   * @param {number} page_size
   */
  async listCollectedTopics(user_id, is_oneself, keyword, tag_name, page_index, page_size) {
    let queryObj = {user_id: user_id};
    if (!is_oneself) {
      queryObj.is_public = true;
    }
    if (tag_name) {
      queryObj.tags = tag_name;
    }
    if (keyword) {
      const realKeyword = [keyword.replace(/\s+/g, '.*')];
      if (is_oneself) {
        queryObj['$or'] = [
          {title: {'$regex': new RegExp(realKeyword, 'i')}},
          {brief: {'$regex': new RegExp(realKeyword, 'i')}}
        ];
      } else {
        queryObj.title = {'$regex': new RegExp(realKeyword, 'i')};
      }
    }

    let opt = {sort: '-updatedAt'};
    if (page_index && page_size) {
      opt.skip = (page_index - 1) * page_size;
      opt.limit = page_size;
    }

    let collects = await this.ctx.model.TopicCollect.find(
      queryObj,
      '',
      opt
    );

    const ids = collects.map(doc => doc.topic_id.toString());
    const query = {_id: {$in: ids}};
    let topics = await this.service.topicSvc.getTopicsByQuery(query, {}, is_oneself);
    topics = _.sortBy(topics, topic => {
      return ids.indexOf(topic._id.toString());
    });

    // 把brief, collect_at, tags字段赋给topics的每一个元素
    // topics.map(v_left => {
    //   collects.map(v_right => {
    //     if (v_left._id.toString() == v_right.topic_id.toString()) {
    //       v_left.collect_at = v_right.updatedAt;
    //       v_left.brief = v_right.brief;
    //       v_left.tags = v_right.tags;
    //       return v_left;
    //     }
    //   });
    // });

    return topics;
  }


  /**
   * 统计用户收藏的文章数量
   * @param {string} user_id 用户id
   * @param {boolean} is_oneself 是否是本人
   * @param {string} keyword 搜索的词
   * @param {string} tag_name 收藏标签名
   */
  async countCollectedTopics(user_id, is_oneself, keyword, tag_name) {
    let queryObj = {user_id: user_id};
    if (!is_oneself) {
      queryObj.is_public = false;
    }
    if (tag_name) {
      queryObj.tags = tag_name;
    }
    if (keyword) {
      const realKeyword = [keyword.replace(/\s+/g, '.*')];
      if (is_oneself) {
        queryObj['$or'] = [
          {title: {'$regex': new RegExp(realKeyword, 'i')}},
          {brief: {'$regex': new RegExp(realKeyword, 'i')}}
        ];
      } else {
        queryObj.title = {'$regex': new RegExp(realKeyword, 'i')};
      }
    }

    return await this.ctx.model.TopicCollect.count(queryObj);
  }


  async listTags(user_id, name) {
    let pipeline = null;
    if (name) {
      pipeline = [
        {$match: {user_id: user_id.toString()}},
        {$unwind: '$tags'},
        {$group: {_id: "$tags", topics_size: {$sum: 1}, sortby: {$max: '$updatedAt'}}},
        {$match: {_id: {'$regex': new RegExp(name, 'i')}}},
        {$sort: {sortby: -1, _id: 1}},
        {$project: {name: '$_id', topics_size: 1, _id: 0}}
      ];
    } else {
      pipeline = [
        {$match: {user_id: user_id.toString()}},
        {$unwind: '$tags'},
        {$group: {_id: "$tags", topics_size: {$sum: 1}, sortby: {$max: '$updatedAt'}}},
        {$sort: {sortby: -1, _id: 1}},
        {$project: {name: '$_id', topics_size: 1, _id: 0}}
      ];
    }
    return await this.ctx.model.TopicCollect.aggregate(pipeline);
  }
}

module.exports = TopicCollectSvc;
